// Load required modules
const dotenv = require('dotenv')
dotenv.config()
const axios = require('axios')
const Router = require('koa-router')
const KoaSSE = require('koa-sse-stream')
const path = require('path')
const fs = require('fs')

// Alibaba Cloud SDK
const { SpeechSynthesizer } = require("alibabacloud-nls")
const RPCClient = require('@alicloud/pop-core')

// OpenAI SDK
const { OpenAI } = require('openai')

// Import imgai2.js
const { generateImageUrl, generateImage } = require('./utils/imgai2.js')

// Create router instance
const router = new Router();

// Initialize OpenAI client
const client = new OpenAI({
	apiKey: `54636a01-aeb0-44d3-a224-d33ca7646c8f`,
	baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
	timeout: 1000 * 60 * 30
})

// Alibaba Cloud NLS token acquisition function
async function getNLSToken() {
	// Create a client for Alibaba Cloud API
	const client = new RPCClient({
		accessKeyId: 'LTAI5tNd3uXFyQvnL1a2TstJ', // Your AccessKey ID
		accessKeySecret: 'veziFeyMBu0ACz6hxgsCpjxu5x1mos', // Your AccessKey Secret
		endpoint: 'http://nls-meta.cn-shanghai.aliyuncs.com',
		apiVersion: '2019-02-28'
	});

	try {
		// Request a new token
		const result = await client.request('CreateToken');
		console.log('Token acquired successfully, expires at:', new Date(result.Token.ExpireTime * 1000).toLocaleString());
		return {
			token: result.Token.Id,
			expireTime: result.Token.ExpireTime
		};
	} catch (error) {
		console.error('Failed to get NLS token:', error);
		// Fallback to the previous token if available (not recommended for production)
		return { token: '56a7a5beff554312a9a766ceeda680f3', expireTime: 0 };
	}
}

// Token cache
let tokenCache = {
	token: null,
	expireTime: 0
};

// Get token with caching
async function getToken() {
	const now = Math.floor(Date.now() / 1000);

	// If token is expired or will expire in the next 5 minutes, get a new one
	if (!tokenCache.token || tokenCache.expireTime - now < 300) {
		const newToken = await getNLSToken();
		tokenCache = newToken;
	}

	return tokenCache.token;
}

function runOnce(text) {
	return new Promise(async rej => {
		let path_ = path.join('./', '/tmp/')
		try {
			fs.mkdirSync(path_)
		} catch (error) { }
		let id = path_ + new Date().getTime() + (Math.random() * 999999).toFixed(0).padEnd(10, '8');
		let dumpFile = fs.createWriteStream(`${id}.mp3`, {
			flags: "w"
		})

		// Get a valid token
		const token = await getToken();

		let tts = new SpeechSynthesizer({
			url: 'wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1',
			appkey: 'vrqenGRTKNgX1fCC',
			token: token
		})

		tts.on("data", (msg) => {
			console.log(`recv size: ${msg.length}`)
			dumpFile.write(msg, "binary", () => {
				// rej(dumpFile)
			})
			// console.log(dumpFile.write(msg, "binary"))
		})
		tts.on("completed", (msg) => {
			console.log("Client recv completed:", msg)
			dumpFile.close()
			rej(id)
		})

		let param = tts.defaultStartParams()
		param.text = text
		param.voice = "zhiyuan"
		param.format = "mp3";
		// 设置返回音频的采样率
		param.sample_rate = 16000;

		try {
			await tts.start(param, true, 6000)
		} catch (error) {
			console.log("error on start:", error)
			return
		} finally {
			//dumpFile.end()
		}
		console.log("synthesis done")
	})
}



// Route implementations
router.get('/speack', async (ctx, next) => {
	let query = ctx?.request?.body || ctx.query
	let {
		text
	} = ctx.query;

	console.log('text', text)

	ctx.response.set("content-type", 'audio/mpeg');
	ctx.set(
		'Content-Disposition',
		`attachment; filename=123.mp3`
	)
	ctx.body = await fs.readFileSync(`${await runOnce(text)}.mp3`);
})

// AI parameters storage
let aiparms = {}
router.post('/aiPutParms', (ctx) => {
	let query = ctx?.request?.body || ctx.query

	let {
		messages,
		model
	} = query;

	let id = new Date().getTime() + (Math.random() * 999999).toFixed(0).padEnd(10, '8');
	aiparms[id] = {
		messages,
		model
	}

	ctx.body = JSON.stringify({
		code: 200,
		id
	})
})

router.get('/ai', KoaSSE({
	pingInterval: 30000
}), async (ctx, next) => {

	let {
		messages,
		model
	} = aiparms[ctx.query.id];

	delete aiparms[ctx.query.id];

	try {
		messages = JSON.parse(messages);
	} catch (error) { }

	console.log('messages', messages)
	setTimeout(async () => {
		const stream = await client.chat.completions.create({
			messages,
			stream: true,
			// max_tokens: 8000,
			model: model || 'ep-20250210200026-cdtrd',
			// model: 'ep-20250210200026-cdtrd',//R1
			// model: 'ep-20250225234229-pgnc8', //v3
			// model: 'ep-20250226203952-hcrvn' ,//r1低配
			// model: 'ep-20250226204501-hszpl' ,//r1中配

			timeout: 1000 * 60 * 30
		})
		for await (const part of stream) {
			const msg = part.choices[0]?.delta;
			console.log('msg', msg)
			if (msg.tool_calls) {
				console.log('tool_calls')
			}
			ctx.sse.send(JSON.stringify(part));
		}
		ctx.sse.sendEnd();
	}, 0)
})

router.get('/getpic', async (ctx, next) => {
	let { searchQuery, limit, skip } = ctx.query;
	let url = `https://api.createporn.com/post/search?limit=${limit || 10}&skip=${skip || 0}&searchQuery=${searchQuery || '自慰'}&sort=hot`

	let res = await axios({
		method: 'get',
		url: url,
		headers: {
			'accept': 'application/json, text/plain, */*',
			'referer': 'https://www.createaiasian.com/',
			'origin': 'https://www.createaiasian.com',
			'x-origin': 'https://www.createaiasian.com',
			'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0'
		}
	});
	res = res.data
	console.log(res)
	ctx.body = res
})

router.get('/getpic2', async (ctx, next) => {
	let { prompt, model, seed, width, height } = ctx.query;
	
	try {
		// Generate image URL using imgai2.js
		const result = await generateImageUrl(prompt || '美女', {
			model: model || 'turbo',
			seed: seed ? parseInt(seed) : Math.floor(Math.random() * 1000000),
			width: width ? parseInt(width) : 1024,
			height: height ? parseInt(height) : 1024
		});

		// Get the image from the URL and return it as a response
		const response = await axios({
			method: 'get',
			url: result.imageUrl,
			responseType: 'arraybuffer',
			headers: {
				'Cache-Control': 'no-cache, no-store, must-revalidate',
				'Pragma': 'no-cache',
				'Expires': '0'
			}
		});

		// Set response headers to prevent caching
		ctx.set('Cache-Control', 'no-cache, no-store, must-revalidate');
		ctx.set('Pragma', 'no-cache');
		ctx.set('Expires', '0');
		ctx.set('Content-Type', 'image/jpeg');
		
		// Return the image data
		ctx.body = response.data;
	} catch (error) {
		console.error('Error in getpic2:', error);
		ctx.status = 500;
		ctx.body = { error: 'Failed to generate or fetch image' };
	}
});

// Export router
module.exports = router; 